#include <string>
#include <cstdlib>
#include "decoder_flac.h"
#include "decoder_flac_metadata.h"
#include "debug.h"

// ======================================
// Methods for Playlist
// ======================================

// ----------------
bool DecoderFLAC::checkFormat(std::string filepath) {
// ----------------
	reader.init(filepath);
	uint32_t tmp;
	reader.read_uint32_be(&tmp, 32);
	if (tmp == 0x664C6143) return true; // check for 'fLaC' header
	return false;
}

// ----------------
fileInfo DecoderFLAC::getInfo() {
// ----------------
	fileInfo info;
	info.type = "FLAC";
	
	// init our metadata processing class
	metaHandler.init(&reader);
	
	// toggle through all blocks
	while (metaHandler.nextBlock())
	{
		FLACmetatype type = metaHandler.getType();
		switch (type)
		{
			case FLAC_ERROR:
			{
				#ifdef DEBUG_DEC_FLAC
				iprintf("[FLAC] Metadata:error\n");
				#endif
				info.type = "ERROR";
				return info;
			}
			break;

			case FLAC_STREAMINFO:
			{
				#ifdef DEBUG_DEC_FLAC
				iprintf("[FLAC] Metadata:streaminfo\n");
				#endif
				streaminfo = metaHandler.readStreaminfo();
			}
			break;

			case FLAC_VORBIS_COMMENT:
			{
				#ifdef DEBUG_DEC_FLAC
				iprintf("[FLAC] Metadata:vorbisComment\n");
				#endif
				FLACvorbis vorCom = metaHandler.readVorbisComment();
				for (u32 i=0; i<vorCom.comments.size(); ++i)
				{
					if (vorCom.comments[i].name == "TITLE") {
						info.title = vorCom.comments[i].data;
					}
					else if (vorCom.comments[i].name == "ARTIST") {
						info.artist = vorCom.comments[i].data;
					}
					else if (vorCom.comments[i].name == "ALBUM") {
						info.album = vorCom.comments[i].data;
					}
					else if (vorCom.comments[i].name == "DATE") {
						info.year = vorCom.comments[i].data;
					}
					else if (vorCom.comments[i].name == "TRACKNUMBER") {
						info.track = vorCom.comments[i].data;
					}
					else if (vorCom.comments[i].name == "TRACKTOTAL") {
						info.alltracks = vorCom.comments[i].data;
					}
					else if (vorCom.comments[i].name == "REPLAYGAIN_REFERENCE_LOUDNESS") {
						info.rgLoudness = atof( vorCom.comments[i].data.data() );
					}
					else if (vorCom.comments[i].name == "REPLAYGAIN_TRACK_GAIN") {
						info.rgTrackGain = atof( vorCom.comments[i].data.data() );
					}
					else if (vorCom.comments[i].name == "REPLAYGAIN_TRACK_PEAK") {
						info.rgTrackPeak = atof( vorCom.comments[i].data.data() );
					}
					else if (vorCom.comments[i].name == "REPLAYGAIN_ALBUM_GAIN") {
						info.rgAlbumGain = atof( vorCom.comments[i].data.data() );
					}
					else if (vorCom.comments[i].name == "REPLAYGAIN_ALBUM_PEAK") {
						info.rgAlbumPeak = atof( vorCom.comments[i].data.data() );
					}
				}
			}
			break;

			case FLAC_PADDING:
			case FLAC_APPLICATION:
			case FLAC_SEEKTABLE:
			case FLAC_CUESHEET:
			case FLAC_PICTURE:
				break;
		}
	}
	
	info.channels = streaminfo.channels;
	info.sampleRate = streaminfo.samplerate;
	info.kbps = (info.sampleRate * info.bits) / 1024;
	info.length = streaminfo.samples;
	info.bits = streaminfo.bitspersample;
	
	return info;
}

// ======================================
// Methods for Player
// ======================================

// ----------------
void DecoderFLAC::prprForPlayback(fileInfo info)
// ----------------
{
	reader.init(info.filepath);
	reader.seek(4);

	// init our metadata processing class
	metaHandler.init(&reader);
	
	// toggle through all blocks
	while (metaHandler.nextBlock())
	{
		FLACmetatype type = metaHandler.getType();
		switch (type)
		{
			case FLAC_ERROR:
			{
				#ifdef DEBUG_DEC_FLAC
				iprintf("[FLAC] Metadata:error\n");
				#endif
				info.type = "ERROR";
			}
			break;

			case FLAC_STREAMINFO:
			{
				#ifdef DEBUG_DEC_FLAC
				iprintf("[FLAC] Metadata:streaminfo\n");
				#endif
				streaminfo = metaHandler.readStreaminfo();
			}
			break;

			case FLAC_SEEKTABLE:
			{
				#ifdef DEBUG_DEC_FLAC
				iprintf("[FLAC] Metadata:seektable\n");
				#endif
				seektable = metaHandler.readSeektable();
			}
			break;

			case FLAC_PADDING:
			case FLAC_APPLICATION:
			case FLAC_CUESHEET:
			case FLAC_PICTURE:
			case FLAC_VORBIS_COMMENT:
				break;
		}
	}

	frameStart = reader.tell();
}

// ----------------
void DecoderFLAC::toFirstSample()
// ----------------
{
	reader.seek(frameStart);
	frameHandler.init(&reader, &streaminfo);
	samplesRead = 0;
	if (!frameHandler.prepare())
	{
		samplesRead = streaminfo.samples;
	}
}

// ----------------
void DecoderFLAC::fillBuffers(int16_t *buffer_l, int16_t *buffer_r, uint32_t samples)
// ----------------
{
	if (!frameHandler.playerCall(buffer_l, buffer_r, samples, &samplesRead))
	{
		samplesRead = streaminfo.samples;
	}
}

// ----------------
uint32_t DecoderFLAC::getCurrentFrame()
// ----------------
{
	return samplesRead;
}

// ----------------
bool DecoderFLAC::reachedEnd()
// ----------------
{
	return (samplesRead >= streaminfo.samples);
}

